// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#include <cantor/type/promote.h>

namespace cantor {
    static constexpr int g_const_tables[pb::TYPE_KIND_NUMERIC_MAX + 1][pb::TYPE_KIND_NUMERIC_MAX + 1]{
        /// from TYPE_KIND_NONE to
        {
            ConvertCostTrait<pb::TYPE_KIND_NONE, pb::TYPE_KIND_NONE>::cost,
            ConvertCostTrait<pb::TYPE_KIND_NONE, pb::TYPE_KIND_INT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_NONE, pb::TYPE_KIND_INT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_NONE, pb::TYPE_KIND_INT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_NONE, pb::TYPE_KIND_INT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_NONE, pb::TYPE_KIND_INT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_NONE, pb::TYPE_KIND_UINT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_NONE, pb::TYPE_KIND_UINT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_NONE, pb::TYPE_KIND_UINT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_NONE, pb::TYPE_KIND_UINT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_NONE, pb::TYPE_KIND_UINT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_NONE, pb::TYPE_KIND_FP8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_NONE, pb::TYPE_KIND_FP16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_NONE, pb::TYPE_KIND_FP32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_NONE, pb::TYPE_KIND_FP64>::cost
        },
        /// from TYPE_KIND_INT8 to
        {
            ConvertCostTrait<pb::TYPE_KIND_INT8, pb::TYPE_KIND_NONE>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT8, pb::TYPE_KIND_INT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT8, pb::TYPE_KIND_INT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT8, pb::TYPE_KIND_INT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT8, pb::TYPE_KIND_INT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT8, pb::TYPE_KIND_INT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT8, pb::TYPE_KIND_UINT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT8, pb::TYPE_KIND_UINT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT8, pb::TYPE_KIND_UINT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT8, pb::TYPE_KIND_UINT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT8, pb::TYPE_KIND_UINT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT8, pb::TYPE_KIND_FP8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT8, pb::TYPE_KIND_FP16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT8, pb::TYPE_KIND_FP32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT8, pb::TYPE_KIND_FP64>::cost
        },
        /// from TYPE_KIND_INT16 to
        {
            ConvertCostTrait<pb::TYPE_KIND_INT16, pb::TYPE_KIND_NONE>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT16, pb::TYPE_KIND_INT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT16, pb::TYPE_KIND_INT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT16, pb::TYPE_KIND_INT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT16, pb::TYPE_KIND_INT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT16, pb::TYPE_KIND_INT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT16, pb::TYPE_KIND_UINT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT16, pb::TYPE_KIND_UINT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT16, pb::TYPE_KIND_UINT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT16, pb::TYPE_KIND_UINT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT16, pb::TYPE_KIND_UINT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT16, pb::TYPE_KIND_FP8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT16, pb::TYPE_KIND_FP16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT16, pb::TYPE_KIND_FP32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT16, pb::TYPE_KIND_FP64>::cost
        },
        /// from TYPE_KIND_INT32 to
        {
            ConvertCostTrait<pb::TYPE_KIND_INT32, pb::TYPE_KIND_NONE>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT32, pb::TYPE_KIND_INT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT32, pb::TYPE_KIND_INT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT32, pb::TYPE_KIND_INT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT32, pb::TYPE_KIND_INT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT32, pb::TYPE_KIND_INT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT32, pb::TYPE_KIND_UINT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT32, pb::TYPE_KIND_UINT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT32, pb::TYPE_KIND_UINT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT32, pb::TYPE_KIND_UINT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT32, pb::TYPE_KIND_UINT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT32, pb::TYPE_KIND_FP8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT32, pb::TYPE_KIND_FP16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT32, pb::TYPE_KIND_FP32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT32, pb::TYPE_KIND_FP64>::cost
        },
        /// from TYPE_KIND_INT64 to
        {
            ConvertCostTrait<pb::TYPE_KIND_INT64, pb::TYPE_KIND_NONE>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT64, pb::TYPE_KIND_INT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT64, pb::TYPE_KIND_INT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT64, pb::TYPE_KIND_INT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT64, pb::TYPE_KIND_INT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT64, pb::TYPE_KIND_INT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT64, pb::TYPE_KIND_UINT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT64, pb::TYPE_KIND_UINT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT64, pb::TYPE_KIND_UINT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT64, pb::TYPE_KIND_UINT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT64, pb::TYPE_KIND_UINT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT64, pb::TYPE_KIND_FP8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT64, pb::TYPE_KIND_FP16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT64, pb::TYPE_KIND_FP32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT64, pb::TYPE_KIND_FP64>::cost
        },
        /// from TYPE_KIND_INT128 to
        {
            ConvertCostTrait<pb::TYPE_KIND_INT128, pb::TYPE_KIND_NONE>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT128, pb::TYPE_KIND_INT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT128, pb::TYPE_KIND_INT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT128, pb::TYPE_KIND_INT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT128, pb::TYPE_KIND_INT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT128, pb::TYPE_KIND_INT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT128, pb::TYPE_KIND_UINT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT128, pb::TYPE_KIND_UINT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT128, pb::TYPE_KIND_UINT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT128, pb::TYPE_KIND_UINT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT128, pb::TYPE_KIND_UINT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT128, pb::TYPE_KIND_FP8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT128, pb::TYPE_KIND_FP16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT128, pb::TYPE_KIND_FP32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_INT128, pb::TYPE_KIND_FP64>::cost
        },
        /// from TYPE_KIND_UINT8 to
        {
            ConvertCostTrait<pb::TYPE_KIND_UINT8, pb::TYPE_KIND_NONE>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT8, pb::TYPE_KIND_INT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT8, pb::TYPE_KIND_INT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT8, pb::TYPE_KIND_INT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT8, pb::TYPE_KIND_INT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT8, pb::TYPE_KIND_INT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT8, pb::TYPE_KIND_UINT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT8, pb::TYPE_KIND_UINT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT8, pb::TYPE_KIND_UINT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT8, pb::TYPE_KIND_UINT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT8, pb::TYPE_KIND_UINT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT8, pb::TYPE_KIND_FP8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT8, pb::TYPE_KIND_FP16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT8, pb::TYPE_KIND_FP32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT8, pb::TYPE_KIND_FP64>::cost
        },
        /// from TYPE_KIND_UINT16 to
        {
            ConvertCostTrait<pb::TYPE_KIND_UINT16, pb::TYPE_KIND_NONE>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT16, pb::TYPE_KIND_INT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT16, pb::TYPE_KIND_INT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT16, pb::TYPE_KIND_INT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT16, pb::TYPE_KIND_INT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT16, pb::TYPE_KIND_INT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT16, pb::TYPE_KIND_UINT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT16, pb::TYPE_KIND_UINT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT16, pb::TYPE_KIND_UINT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT16, pb::TYPE_KIND_UINT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT16, pb::TYPE_KIND_UINT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT16, pb::TYPE_KIND_FP8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT16, pb::TYPE_KIND_FP16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT16, pb::TYPE_KIND_FP32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT16, pb::TYPE_KIND_FP64>::cost
        },
        /// from TYPE_KIND_UINT32 to
        {
            ConvertCostTrait<pb::TYPE_KIND_UINT32, pb::TYPE_KIND_NONE>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT32, pb::TYPE_KIND_INT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT32, pb::TYPE_KIND_INT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT32, pb::TYPE_KIND_INT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT32, pb::TYPE_KIND_INT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT32, pb::TYPE_KIND_INT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT32, pb::TYPE_KIND_UINT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT32, pb::TYPE_KIND_UINT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT32, pb::TYPE_KIND_UINT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT32, pb::TYPE_KIND_UINT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT32, pb::TYPE_KIND_UINT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT32, pb::TYPE_KIND_FP8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT32, pb::TYPE_KIND_FP16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT32, pb::TYPE_KIND_FP32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT32, pb::TYPE_KIND_FP64>::cost
        },
        /// from TYPE_KIND_UINT64 to
        {
            ConvertCostTrait<pb::TYPE_KIND_UINT64, pb::TYPE_KIND_NONE>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT64, pb::TYPE_KIND_INT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT64, pb::TYPE_KIND_INT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT64, pb::TYPE_KIND_INT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT64, pb::TYPE_KIND_INT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT64, pb::TYPE_KIND_INT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT64, pb::TYPE_KIND_UINT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT64, pb::TYPE_KIND_UINT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT64, pb::TYPE_KIND_UINT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT64, pb::TYPE_KIND_UINT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT64, pb::TYPE_KIND_UINT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT64, pb::TYPE_KIND_FP8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT64, pb::TYPE_KIND_FP16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT64, pb::TYPE_KIND_FP32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT64, pb::TYPE_KIND_FP64>::cost
        },
        /// from TYPE_KIND_UINT128 to
        {
            ConvertCostTrait<pb::TYPE_KIND_UINT128, pb::TYPE_KIND_NONE>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT128, pb::TYPE_KIND_INT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT128, pb::TYPE_KIND_INT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT128, pb::TYPE_KIND_INT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT128, pb::TYPE_KIND_INT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT128, pb::TYPE_KIND_INT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT128, pb::TYPE_KIND_UINT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT128, pb::TYPE_KIND_UINT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT128, pb::TYPE_KIND_UINT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT128, pb::TYPE_KIND_UINT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT128, pb::TYPE_KIND_UINT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT128, pb::TYPE_KIND_FP8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT128, pb::TYPE_KIND_FP16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT128, pb::TYPE_KIND_FP32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_UINT128, pb::TYPE_KIND_FP64>::cost
        },
        /// from TYPE_KIND_FP8 to
        {
            ConvertCostTrait<pb::TYPE_KIND_FP8, pb::TYPE_KIND_NONE>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP8, pb::TYPE_KIND_INT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP8, pb::TYPE_KIND_INT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP8, pb::TYPE_KIND_INT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP8, pb::TYPE_KIND_INT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP8, pb::TYPE_KIND_INT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP8, pb::TYPE_KIND_UINT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP8, pb::TYPE_KIND_UINT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP8, pb::TYPE_KIND_UINT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP8, pb::TYPE_KIND_UINT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP8, pb::TYPE_KIND_UINT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP8, pb::TYPE_KIND_FP8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP8, pb::TYPE_KIND_FP16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP8, pb::TYPE_KIND_FP32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP8, pb::TYPE_KIND_FP64>::cost
        },
        /// from TYPE_KIND_FP16 to
        {
            ConvertCostTrait<pb::TYPE_KIND_FP16, pb::TYPE_KIND_NONE>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP16, pb::TYPE_KIND_INT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP16, pb::TYPE_KIND_INT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP16, pb::TYPE_KIND_INT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP16, pb::TYPE_KIND_INT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP16, pb::TYPE_KIND_INT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP16, pb::TYPE_KIND_UINT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP16, pb::TYPE_KIND_UINT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP16, pb::TYPE_KIND_UINT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP16, pb::TYPE_KIND_UINT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP16, pb::TYPE_KIND_UINT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP16, pb::TYPE_KIND_FP8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP16, pb::TYPE_KIND_FP16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP16, pb::TYPE_KIND_FP32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP16, pb::TYPE_KIND_FP64>::cost
        },
        /// from TYPE_KIND_FP32 to
        {
            ConvertCostTrait<pb::TYPE_KIND_FP32, pb::TYPE_KIND_NONE>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP32, pb::TYPE_KIND_INT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP32, pb::TYPE_KIND_INT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP32, pb::TYPE_KIND_INT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP32, pb::TYPE_KIND_INT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP32, pb::TYPE_KIND_INT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP32, pb::TYPE_KIND_UINT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP32, pb::TYPE_KIND_UINT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP32, pb::TYPE_KIND_UINT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP32, pb::TYPE_KIND_UINT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP32, pb::TYPE_KIND_UINT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP32, pb::TYPE_KIND_FP8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP32, pb::TYPE_KIND_FP16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP32, pb::TYPE_KIND_FP32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP32, pb::TYPE_KIND_FP64>::cost
        },
        /// from TYPE_KIND_FP64 to
        {
            ConvertCostTrait<pb::TYPE_KIND_FP64, pb::TYPE_KIND_NONE>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP64, pb::TYPE_KIND_INT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP64, pb::TYPE_KIND_INT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP64, pb::TYPE_KIND_INT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP64, pb::TYPE_KIND_INT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP64, pb::TYPE_KIND_INT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP64, pb::TYPE_KIND_UINT8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP64, pb::TYPE_KIND_UINT16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP64, pb::TYPE_KIND_UINT32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP64, pb::TYPE_KIND_UINT64>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP64, pb::TYPE_KIND_UINT128>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP64, pb::TYPE_KIND_FP8>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP64, pb::TYPE_KIND_FP16>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP64, pb::TYPE_KIND_FP32>::cost,
            ConvertCostTrait<pb::TYPE_KIND_FP64, pb::TYPE_KIND_FP64>::cost
        }
    };

    int32_t promote_cost(const pb::TypeInfo &from, const pb::TypeInfo &to) {
        if (from.type() > pb::TYPE_KIND_NUMERIC_MAX || to.type() < pb::TYPE_KIND_NONE) {
            return -2;
        }
        if (to.type() > pb::TYPE_KIND_NUMERIC_MAX || to.type() < pb::TYPE_KIND_NONE) {
            return -2;
        }
        return g_const_tables[from.type()][to.type()];
    }

    bool type_equal(const pb::TypeInfo &from, const pb::TypeInfo &to) {
        if (from.type() != to.type()) {
            return false;
        }
        switch (from.type()) {
            case pb::TYPE_KIND_INT8:

            case pb::TYPE_KIND_INT16:
            case pb::TYPE_KIND_UINT16:
            case pb::TYPE_KIND_INT32:
            case pb::TYPE_KIND_INT64:
            case pb::TYPE_KIND_INT128:
            case pb::TYPE_KIND_UINT8:
            case pb::TYPE_KIND_UINT32:
            case pb::TYPE_KIND_UINT64:
            case pb::TYPE_KIND_UINT128:
            case pb::TYPE_KIND_FP8:
            case pb::TYPE_KIND_FP16:
            case pb::TYPE_KIND_FP64:
            case pb::TYPE_KIND_STRING:
            case pb::TYPE_KIND_BINARY:
            case pb::TYPE_KIND_TIMESTAMP:
            case pb::TYPE_KIND_DURATION:
            case pb::TYPE_KIND_BOOLEAN:
            case pb::TYPE_KIND_DATETIME:
            case pb::TYPE_KIND_INTERVAL:
                return true;
            case pb::TYPE_KIND_DECIMAL64: {
                auto &df = from.decimal64_type();
                auto &dt = to.decimal64_type();
                return df.precision() == dt.precision() && df.scale() == dt.scale();
            }

            case pb::TYPE_KIND_DECIMAL128: {
                auto &df = from.decimal128_type();
                auto &dt = to.decimal128_type();
                return df.precision() == dt.precision() && df.scale() == dt.scale();
            }

            case pb::TYPE_KIND_ENUM: {
                auto &df = from.enum_type();
                auto &dt = to.enum_type();
                return df.uri() == dt.uri();
            }
            case pb::TYPE_KIND_ARRAY: {
                auto &df = from.array_type();
                auto &dt = to.array_type();
                return type_equal(df.type(), dt.type());
            }
            case pb::TYPE_KIND_MAP: {
                auto &df = from.map_type();
                auto &dt = to.map_type();
                return type_equal(df.key(), dt.key()) && type_equal(df.value(), dt.value());
            }
            case pb::TYPE_KIND_SET: {
                auto &df = from.set_type();
                auto &dt = to.set_type();
                return type_equal(df.key(), dt.key());
            }
            case pb::TYPE_KIND_STRUCT: {
                auto &df = from.struct_type();
                auto &dt = to.struct_type();
                if (df.names_size() != dt.names_size()) {
                    return false;
                }
                for (auto i = 0; i < df.names_size(); i++) {
                    if (df.names(i) != dt.names(i)) {
                        return false;
                    }
                    if (!type_equal(df.types(i), dt.types(i))) {
                        return false;
                    }
                }
                return true;
            }

            case pb::TYPE_KIND_UNION: {
                auto &df = from.union_type();
                auto &dt = to.union_type();
                if (df.names_size() != dt.names_size()) {
                    return false;
                }
                for (auto i = 0; i < df.names_size(); i++) {
                    if (df.names(i) != dt.names(i)) {
                        return false;
                    }
                    if (!type_equal(df.types(i), dt.types(i))) {
                        return false;
                    }
                }
                return true;
            }
            case pb::TYPE_KIND_TUPLE: {
                auto &df = from.tuple_type();
                auto &dt = to.tuple_type();
                if (df.types_size() != dt.types_size()) {
                    return false;
                }
                for (auto i = 0; i < df.types_size(); i++) {
                    if (!type_equal(df.types(i), dt.types(i))) {
                        return false;
                    }
                }
                return true;
            }
            case pb::TYPE_KIND_JSON: {
                auto &df = from.json_type();
                auto &dt = to.json_type();
                if (df.has_schema() && dt.has_schema()) {
                    return df.schema() == dt.schema();
                }
                if (!df.has_schema() && !dt.has_schema()) {
                    return true;
                }
                return false;
            }
            case pb::TYPE_KIND_PROTO: {
                auto &df = from.proto_type();
                auto &dt = to.proto_type();
                return df.uri() == dt.uri();
            }
            default:
                return false;
        }
    }
}
